#include <sxMSM_PreviewState.h>
#include <sxMappedSurface.h>

Sx::Simulation::Recording::MSM_PreviewState::MSM_PreviewState() {}
Sx::Simulation::Recording::MSM_PreviewState::~MSM_PreviewState() {}

bool Sx::Simulation::Recording::MSM_PreviewState::save(const std::shared_ptr<MassSpringMesh>& massSpringMesh) {
	const std::shared_ptr<Mesh>& mesh = massSpringMesh->getObject();
	const std::shared_ptr<MassSpringSystem>& massSpringSystem = massSpringMesh->getPhysicalRepresentation();

	//--------------------------------------------------------------------------
	// Copy the mesh surface from the mass-spring mesh.
	//--------------------------------------------------------------------------
	this->mesh.setSurface(mesh->getSurface());
	this->mesh.setColor(mesh->getColor());
	
	//--------------------------------------------------------------------------
	// Copy the dynamic state of the mass-spring mesh.
	//--------------------------------------------------------------------------
	Util::ArrayList<Eigen::Vector3d>& meshVertices = massSpringSystem->getVertices();
	Util::ArrayList<Eigen::Vector3d>& meshVelocities = massSpringSystem->state.velocities;
	Util::ArrayList<Eigen::Vector3d>& meshAccelerations = massSpringSystem->state.accelerations;
	Util::ArrayList<Eigen::Vector3d>& meshExternalForces = massSpringSystem->state.externalForces;
	Util::ArrayList<Eigen::Vector3d>& meshInternalForces = massSpringSystem->state.internalForces;

	const unsigned int nodeCount = meshVertices.size();
	this->meshPreviewStorage.vertices.resize(nodeCount);
	this->meshPreviewStorage.state.velocities.resize(nodeCount);
	this->meshPreviewStorage.state.accelerations.resize(nodeCount);
	this->meshPreviewStorage.state.externalForces.resize(nodeCount);
	this->meshPreviewStorage.state.internalForces.resize(nodeCount);

	//--------------------------------------------------------------------------
	// Copy that state data from the mass-spring mesh into the stored rep.
	// The transformation must also be applied!
	//--------------------------------------------------------------------------
	Eigen::Vector3d tPosition;
	for ( unsigned int i = 0; i < nodeCount; i++ ) {
		mesh->transformPointToGlobal(meshVertices[i], tPosition);
		this->meshPreviewStorage.vertices[i] = tPosition;
		this->meshPreviewStorage.state.velocities[i] = meshVelocities[i];
		this->meshPreviewStorage.state.accelerations[i] = meshAccelerations[i];
		this->meshPreviewStorage.state.externalForces[i] = meshExternalForces[i];
		this->meshPreviewStorage.state.internalForces[i] = meshInternalForces[i];
	}

	return false;
}

/* Copy the data from the internal storage to the provided archetype. */
bool Sx::Simulation::Recording::MSM_PreviewState::load(StoredMesh_Archetype& pStoredMesh) {
	return pStoredMesh.setStoredData(this->mesh, this->meshPreviewStorage);
}
